/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package Wires.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.m2m.atl.engine.AtlEMFModelHandler;

import Wires.AtomicModelTransformation;
import Wires.CompositeTransformation;
import Wires.ConnectableElement;
import Wires.GenericTransformation;
import Wires.IdentityTransformation;
import Wires.InputFormalParameter;
import Wires.Model;
import Wires.OutputActualParameter;
import Wires.WiresPackage;
import Wires.exep.ResourceNotFoundException;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Model</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link Wires.impl.ModelImpl#getPath <em>Path</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class ModelImpl extends TypedElementImpl implements Model {
	/***************************************************/
	/***************** Modifications *******************/
	
	public void execute(ConnectableElement incoming) throws IOException{
		
		if (incoming instanceof Model){	
			//Copy the model file			
			String inPath = ((Model) incoming).getPath();		
			String outPath = ((Model) this).getPath();
			
			File in = null;
			try {
				in = new File(inPath);
			} catch (Exception e) {
				throw new ResourceNotFoundException(incoming);
			}
			File out = null;
			try {
				out = new File (outPath);
			} catch (Exception e) {
				throw new ResourceNotFoundException(this);
			}
			
			copy(in,out);	
		}else if (incoming instanceof OutputActualParameter){
			//IdentityTransformation OutputParameter to Model
			if (((OutputActualParameter) incoming).eContainer() instanceof IdentityTransformation ||
					(((OutputActualParameter) incoming).eContainer() instanceof CompositeTransformation &&
						((OutputActualParameterImpl) incoming).getModel() == null)){
				File in = null;
				try {
					in = new File(((OutputActualParameterImpl) incoming).getModelPath());
				} catch (Exception e) {
					throw new ResourceNotFoundException(incoming);
				}
				File out = null;
				try {
					out = new File (((ModelImpl) this).getPath());					
				} catch (Exception e) {
					throw new ResourceNotFoundException(this);
				}
				copy(in,out);
			//AtomicModelTransformation or GenericTransformation OutputParameter Model
			}else if (((OutputActualParameter) incoming).eContainer() instanceof AtomicModelTransformation
					|| ((OutputActualParameter) incoming).eContainer() instanceof GenericTransformation
					|| ((OutputActualParameter) incoming).eContainer() instanceof CompositeTransformation){
				//Save model in a File
				AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
				String modelPath = this.getPath();
				File f = null;
				try {
					f = new File(modelPath);
				} catch (Exception e) {
					throw new ResourceNotFoundException(this);
				}
				if (f.exists())
					f.delete();
				modelHandler.saveModel(((OutputActualParameterImpl)incoming).getModel(), modelPath, false);
			}
		}else if (incoming instanceof InputFormalParameter){
			//Save model in a File
			AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
			String modelPath = this.getPath();
			File f = null;
			try {
				f = new File(modelPath);
			} catch (Exception e) {
				throw new ResourceNotFoundException(this);
			}
			if (f.exists())
				f.delete();
			modelHandler.saveModel(((InputFormalParameterImpl)incoming).getModel(), modelPath, false);
		}
 	}
		
    private void copy(File src, File dst) throws IOException {
    	if (dst.exists())
        	dst.delete();
    	
    	InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst);               
                
        byte[] buf = new byte[4096];
        int len;
        while ((len = in.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }
    
	
	/**************** Modifications End ****************/
	/***************************************************/
	
	/**
	 * The default value of the '{@link #getPath() <em>Path</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getPath()
	 * @generated
	 * @ordered
	 */
	protected static final String PATH_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getPath() <em>Path</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getPath()
	 * @generated
	 * @ordered
	 */
	protected String path = PATH_EDEFAULT;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected ModelImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return WiresPackage.Literals.MODEL;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public String getPath() {
		return path;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setPath(String newPath) {
		String oldPath = path;
		path = newPath;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, WiresPackage.MODEL__PATH, oldPath, path));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case WiresPackage.MODEL__PATH:
				return getPath();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case WiresPackage.MODEL__PATH:
				setPath((String)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case WiresPackage.MODEL__PATH:
				setPath(PATH_EDEFAULT);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case WiresPackage.MODEL__PATH:
				return PATH_EDEFAULT == null ? path != null : !PATH_EDEFAULT.equals(path);
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (path: ");
		result.append(path);
		result.append(')');
		return result.toString();
	}

} //ModelImpl
